#pragma once

namespace Data_RenderData
{
	enum EBufferFormat 
	{ 
		EBufferFormat_Invalid,
		EBufferFormat_VertexStream,
		EBufferFormat_Index16Stream,
		EBufferFormat_Index32Stream,
		EBufferFormat_ConstantBuffer,
		EBufferFormat_R8G8B8A8,
		EBufferFormat_R8G8B8,
		EBufferFormat_R5G6B5,
		EBufferFormat_RGBA16F,
		EBufferFormat_RGBA32F,
		EBufferFormat_DXT1,
		EBufferFormat_DXT2,
		EBufferFormat_DXT3,
		EBufferFormat_DXT4,
		EBufferFormat_DXT5,
		EBufferFormat_D24S8,
		EBufferFormat_D16,
		EBufferFormat_D32
	};

	struct BufferDeclarationElement
	{
		cr::uint32_t				m_name;
		cr::uint32_t				m_semantic;
		cr::uint32_t				m_numElements;
		cr::uint32_t				m_offset;
		cr::uint32_t				m_type;
	};

	struct BufferDeclaration
	{
		cr::int32_t					m_idxFirstElement;
		cr::uint32_t				m_numElements;
		cr::uint32_t				m_stride;
		cr::uint32_t				m_runtimeData;
	};

	struct Buffer
	{
		cr::uint32_t				m_numElements;
		EBufferFormat				m_format;
		cr::int32_t					m_idxBufferDeclaration;
		cr::int32_t					m_idxInitData;
		cr::uint32_t				m_numInitDataBytes;
		cr::uint32_t				m_runtimeData;
	};

	struct Texture
	{
		cr::int32_t					m_idxInitData;
		cr::uint32_t				m_numInitDataBytes;
		cr::uint32_t				m_runtimeData;
	};

	struct Parameter
	{
		cr::uint32_t				m_name;
		cr::uint32_t				m_type;
		cr::int32_t					m_idxInitData;
		cr::uint32_t				m_numInitDataBytes;
	};

	struct GpuProgram
	{
		cr::uint32_t				m_name;
		cr::uint32_t				m_idxInitDataBytes;
		cr::uint32_t				m_numInitDataBytes;
		cr::uint32_t				m_runtimeData;
	};

	struct RenderMethod
	{
		cr::int32_t					m_idxGpuProgram;
		cr::int32_t					m_idxFirstParameter;
		cr::uint32_t				m_numParameters;
	};

	struct Material
	{
		cr::uint32_t				m_name;
		cr::int32_t					m_idxFirstRenderMethod;
		cr::uint32_t				m_numRenderMethods;
		cr::int32_t					m_idxFirstMaterialParam;
		cr::uint32_t				m_numMaterialParams;
		cr::uint32_t				m_runtimeData;
	};

	struct Submodel
	{
		cr::uint32_t				m_firstVertex;
		cr::uint32_t				m_numVertices;
		cr::uint32_t				m_firstIndex;
		cr::uint32_t				m_numIndices;
		cr::int32_t					m_idxMaterial;
		cr::int32_t					m_idxIndexBuffer;
		cr::int32_t					m_idxVertexBuffer;
		cr::uint32_t				m_flags;
		cr::uint32_t				m_runtimeData;
	};

	struct ModelLod
	{
		cr::int32_t					m_idxFirstSubModel;
		cr::uint32_t				m_numSubModels;
		cr::uint32_t				m_flags;
	};

	struct Model
	{
		cr::uint32_t				m_name;
		cr::int32_t					m_idxFirstLod;
		cr::uint32_t				m_numLods;
		cr::uint32_t				m_flags;
	};

	struct Instance
	{
		cr::uint32_t				m_name;
		cr::int32_t					m_idxModel;
		cr::int32_t					m_idxTransform;
		cr::uint32_t				m_flags;
	};

	struct Transform
	{
		float						m_translation[3];
		float						m_scale[3];
		float						m_rotation[3];
	};

	struct RenderData
	{
		cr::uint32_t				m_numTransforms;
		Transform*					m_pTransforms;
		cr::uint32_t				m_numInstances;
		Instance*					m_pInstances;
		cr::uint32_t				m_numModels;
		Model*						m_pModels;
		cr::uint32_t				m_numModelLods;
		ModelLod*					m_pModelLods;
		cr::uint32_t				m_numSubmodels;
		Submodel*					m_pSubmodels;
		cr::uint32_t				m_numMaterials;
		Material*					m_pMaterials;
		cr::uint32_t				m_numRenderMethods;
		RenderMethod*				m_pRenderMethods;
		cr::uint32_t				m_numGpuPrograms;
		GpuProgram*					m_pGpuPrograms;
		cr::uint32_t				m_numParameters;
		Parameter*					m_pParameters;
		cr::uint32_t				m_numTextures;
		Texture*					m_pTextures;
		cr::uint32_t				m_numBuffers;
		Buffer*						m_pBuffers;
		cr::uint32_t				m_numBufferDeclarations;
		BufferDeclaration*			m_pBufferDeclarations;
		cr::uint32_t				m_numBufferDeclarationElements;
		BufferDeclarationElement*	m_pBufferDeclarationElements;
		cr::uint32_t				m_numRawBytes;
		cr::uint8_t*				m_pRawBytes;

		void Fixup()
		{
			#define FIXUP(t,p)	{ p = (t*)(((char*)(this+1)) + (int)p); }

			FIXUP(Transform, m_pTransforms);
			FIXUP(Instance, m_pInstances);
			FIXUP(Model, m_pModels);
			FIXUP(ModelLod, m_pModelLods);
			FIXUP(Submodel, m_pSubmodels);
			FIXUP(Material, m_pMaterials);
			FIXUP(RenderMethod, m_pRenderMethods);
			FIXUP(GpuProgram, m_pGpuPrograms);
			FIXUP(Parameter, m_pParameters);
			FIXUP(Texture, m_pTextures);
			FIXUP(Buffer, m_pBuffers);
			FIXUP(BufferDeclaration, m_pBufferDeclarations);
			FIXUP(BufferDeclarationElement, m_pBufferDeclarationElements);
			FIXUP(cr::uint8_t, m_pRawBytes);

			#undef FIXUP
		}
	};
}